home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / compress / tar321__.zip / SOURCES.ZIP / EXTRACT.C < prev    next >
C/C++ Source or Header  |  1997-03-30  |  15KB  |  525 lines

  1. /* extarct.c - extract files from (tape) archive.
  2.  * This is a part of the Tar program (see file tar.c)
  3.  * Author: T.V.Shaporev
  4.  * Creation date: 14 Dec 1990
  5.  */
  6. #include <stdio.h>
  7.  
  8. #include "sysup.h"
  9. #include "nodedef.h"
  10. #include "modern.h"
  11. #ifdef MODERN
  12. #    include <string.h>
  13. #else
  14.     char *strncpy();
  15.     int  strlen();
  16. #endif
  17. #ifndef MSDOS
  18.     int  mknod(), chown(), utime();
  19.     long time();
  20. #endif
  21.  
  22. #include "zippipe.h"
  23. #include "zipdefs.h"
  24. #include "lzwbits.h"
  25. #include "lzwhead.h"
  26. #include "compress.h"
  27. #include "define.h"
  28. #include "lzpack.h"
  29.  
  30. static int soctus   __ARGS__(( register char *, register short* ));
  31.        int soctul   __ARGS__(( register char *, register long * ));
  32.        int shexul   __ARGS__(( register char *, register long * ));
  33.  
  34. #define octal(c) (((c)&0370)=='0')
  35.  
  36. static char unknown[] = "Tar: \'%s\' unknown file type \'%c\'\n";
  37. #define _unknown (unknown+9)
  38.  
  39. static int soctus(s, u)
  40. register short *u;
  41. register char *s;
  42. {
  43.    register i;
  44.    while (*s == ' ') ++s;
  45.    for (*u=0, i=0; octal(*s) && i<7; i++, s++) *u = (*u<<3)|(*s&7);
  46.    return *s!=' ' && *s!='\0';
  47. }
  48.  
  49. int soctul(s, u)
  50. register long *u;
  51. register char *s;
  52. {
  53.    register i;
  54.    while (*s == ' ') ++s;
  55.    for (*u=0, i=0; octal(*s) && i<11; i++, s++) *u = (*u<<3)|(*s&7);
  56.    return *s!=' ' && *s!='\0';
  57. }
  58.  
  59. int shexul(s, u)
  60. register long *u;
  61. register char *s;
  62. {
  63.    register i, k;
  64.    while (*s == ' ') ++s;
  65.    for (*u=0, i=0; i<8; i++, s++) {
  66.       k = *s;
  67.       if      (k >= '0' && k <= '9') k -= '0';
  68.       else if (k >= 'A' && k <= 'F') k -= 'A'-10;
  69.       else if (k >= 'a' && k <= 'f') k -= 'a'-10;
  70.       else break;
  71.       *u = (*u << 4) | k;
  72.    }
  73.    return *s!=' ' && *s!='\0';
  74. }
  75.  
  76. int pktest(p)
  77. unsigned char *p;
  78. {
  79.    register unsigned k;
  80.  
  81.    if (pklock || i_flag || pktype != PKNONE) return ERROR;
  82.    pklock = TRUE;
  83.  
  84.    k = ((unsigned)(p[1]) << 8) | p[0];
  85.    if (k == (unsigned)((LZW_1ST_MAGIC << 8) | LZW_0TH_MAGIC)) {
  86.       pktype = PKpLZW;
  87.    } else if (k == GZIP_MAGIC || (k == PKW_01_MAGIC &&
  88.              (((unsigned)(p[3]) << 8) | p[2]) == PKW_23_MAGIC)) {
  89.       pktype = PKZIP;
  90.    } else {
  91.       return ERROR;
  92.    }
  93.    if (pkalloc()) {
  94.       (void)fprintf(stderr, "No memory for decompression\n");
  95.       done(ESMALL);
  96.    }
  97.    if (redirect()) done(EINTER);
  98.    return CORRECT;
  99. }
  100.  
  101. int gethead()
  102. {
  103.    short n;
  104.    static short errcount = 0;
  105.    register char *err_text = "Tar: bad directory structure\n";
  106.  
  107.    for (;;) {
  108.       if ((hblock = readtape()) == NULL) return ERROR;
  109.       if ((hblock->m.name[0]) == '\0') {
  110.          return errcount ? (++errcount, ERROR) : FALSE;
  111.       }
  112.       if (soctus(hblock->m.chksum, &n) == CORRECT) {
  113.          if (n == headsum(hblock)) break;
  114.          err_text = "Tar: directory checksum error\n";
  115.       }
  116.       if (pktest((unsigned char*)(hblock->m.name))) goto bad;
  117.    }
  118.    if (soctus(hblock->m.mode,  (short*)&(st.st_mode)) ||
  119.        soctus(hblock->m.uid,   (short*)&(st.st_uid))  ||
  120.        soctus(hblock->m.gid,   (short*)&(st.st_gid))  ||
  121.        soctul(hblock->m.size,  (long *)&(st.st_size)) ||
  122.        soctul(hblock->m.mtime, (long *)&(st.st_mtime))) goto bad;
  123.    if (hblock->m.filetype == TF_CHR || hblock->m.filetype == TF_BLK) {
  124.       if (soctus(hblock->x.devmajor, &dmajor) ||
  125.           soctus(hblock->x.devminor, &dminor)) goto bad;
  126.    }
  127.    if (errcount != 0) {
  128.       (void)fprintf(myout,
  129.                     "Tar: %d blocks skipped to find header\n", errcount);
  130.       errcount = 0;
  131.    }
  132.    if (hblock->m.filetype != TF_OLD && hblock->m.filetype != TF_REG) {
  133.       longcsum = codesize = 0L;
  134.    } else if (hblock->m.srcsum[1]!='x' || hblock->m.srcsum[0]!='0') {
  135.       (void)soctul(hblock->m.srclen, &codesize); /* no sence for    */
  136.       (void)soctul(hblock->m.srcsum, &longcsum); /* non-packed file */
  137.    } else {
  138.       (void)shexul(hblock->m.srclen + 2, &codesize);
  139.       (void)shexul(hblock->m.srcsum + 2, &longcsum);
  140.    }
  141.    return TRUE;
  142. bad:
  143.    if (errcount++ == 0) (void)fprintf(myout, err_text);
  144.    if (!i_flag) done(ERREAD);
  145.    return ERROR;
  146. }
  147.  
  148. static int tstfield __ARGS__(( char *, int ));
  149.  
  150. static int tstfield(s,n) /* is the field a valid octal number? */
  151. char *s; int n;
  152. {
  153.    register j;
  154.  
  155.    for (j=0; j<n && octal(s[j]); j++);
  156.    if (!j || j >= n) return FALSE;
  157.    if (s[j] == ' ') ++j;
  158.    while (j<n && !s[j++]);
  159.    return j>=n;
  160. }
  161.  
  162. #define TstField(x) tstfield(x, sizeof(x))
  163.  
  164. short isextent(allx, allb)
  165. short *allx; long *allb;
  166. {
  167.    short n;
  168.  
  169.    if ((hblock->m.filetype != TF_OLD && hblock->m.filetype != TF_REG) ||
  170.        !TstField(hblock->s.extent) ||
  171.        !TstField(hblock->s.allext) ||
  172.        !TstField(hblock->s.total)) return ERROR;
  173.    (void)soctus(hblock->s.extent, &n);
  174.    (void)soctus(hblock->s.allext, allx);
  175.    (void)soctul(hblock->s.total,  allb);
  176.    return n < 1 || n > *allx || *allb <= st.st_size ? ERROR : n;
  177. }
  178.  
  179. int ismagic()
  180. {
  181.    register i;
  182.    register char *p, *q;
  183.    static char magic_list[][8] = { TMAGIC, GMAGIC };
  184.  
  185.    if (hblock->m.filetype != TF_OLD) {
  186.       for (i=0; i<dimof(magic_list); i++) {
  187.          p = magic_list[i];
  188.          q = hblock->x.magic;
  189.          while (*q && *q == *p) {
  190.             ++q; p++;
  191.          }
  192.          if (*q == '\0' && (*p == '\0' || *p == ' '))
  193.             return magic_list[i][0];
  194.       }
  195.    }
  196.    return 0;
  197. }
  198.  
  199. char prefix()
  200. {
  201.    switch (hblock->m.filetype) {
  202.       case TF_CTG: /* ??? contiguous file */
  203.       case TF_OLD:
  204.       case TF_REG:
  205.       case TF_LNK: return ' ';
  206.       case TF_SYM: return 'l';
  207.       case TF_CHR: return 'c';
  208.       case TF_BLK: return 'b';
  209.       case TF_DIR: return 'd';
  210.       case TF_QUE: return 'p';
  211.       case GF_DMP: return 'D';
  212.       case GF_MUL: return ',';
  213.       case GF_VOL: return 'v';
  214.    }
  215.    return '?';
  216. }
  217.  
  218. int usize() /* is it valid to use file size in header */
  219. {
  220.    switch (hblock->m.filetype) {
  221.       case TF_OLD: case TF_REG: case TF_CTG:
  222.       case GF_DMP: case GF_MUL: case GF_SPR: /* what's it? I wonder */
  223.          return TRUE;
  224.    }
  225.    return FALSE;
  226. }
  227.  
  228. void skipfile()
  229. {
  230.    register long blocks;
  231.  
  232.    for (blocks=(st.st_size+BLKSIZE-1)/BLKSIZE; blocks>0; blocks--) {
  233.       if (readtape() == NULL) {
  234.          (void)fprintf(myout, "Tar: tape read error\n");
  235.          if (i_flag) done(ERREAD);
  236.          return;
  237.       }
  238.    }
  239. }
  240.  
  241. static inlist __ARGS__((int, char**, char*));
  242.  
  243. static int inlist(argc, argv, n)
  244. int argc; register char *argv[], *n;
  245. {
  246.    register i; register j; register k;
  247.    register char *p;
  248.  
  249.    for (i=0; i<argc; i++) {
  250.       if (s_flag) {
  251.          for (p=argv[i], j=0; j<MAXTNAME && p[j]==n[j] && p[j]!=0; j++);
  252.          if (j<MAXTNAME && p[j]==0 && (n[j]==0 || n[j]=='/')) return TRUE;
  253.       } else {
  254.          for (j=0; j<MAXTNAME && n[j];) {
  255.             do ++j; while (n[j]!='/' && n[j]!=0);
  256.             if ((k = mismatch(argv[i], n, j)) == ERROR) break;
  257.             if (!k) return TRUE;
  258.          }
  259.       }
  260.    }
  261.    return FALSE;
  262. }
  263.  
  264. int inargs(argc, argv, n)
  265. int argc; char *argv[], *n;
  266. {
  267.    return inlist(argc, argv, n) && !inlist(xcnt, xarg, n);
  268. }
  269.  
  270. void scantape(argc, argv, handler)
  271. int argc; char *argv[]; void (*handler)__ARGS__((void));
  272. {
  273.    register k;
  274.    register char *p;
  275.  
  276. #ifdef MSDOS
  277.    for (k=0; k<argc; k++) for (p=argv[k]; *p; p++) if (*p=='\\') *p='/';
  278.    for (k=0; k<xcnt; k++) for (p=xarg[k]; *p; p++) if (*p=='\\') *p='/';
  279. #endif
  280.    while ((k=gethead()) != FALSE) {
  281.       pklock = TRUE;
  282.       if (k == ERROR) continue;
  283.       if ((argc < 1 ||  inlist(argc, argv, hblock->m.name)) &&
  284.           (xcnt < 1 || !inlist(xcnt, xarg, hblock->m.name))) {
  285.          (*handler)();
  286.       } else {
  287.          if (usize()) skipfile();
  288.       }
  289.    }
  290.    if (pktype == PKZIP) {
  291.       while ((k=unzread((char*)hblock, BLKSIZE)) == BLKSIZE);
  292.       if (k != ERROR) {
  293.          if (k) (void)fprintf(myout, "Tar: final block misaligned\n");
  294.          k = unzclose();
  295.       }
  296.       if (k) {
  297.          p = k == -1 ? "error" : v_flag ? "warning" : NULL;
  298.          if (p) (void)fprintf(myout, "Tar: unzip %s: %s\n",
  299.                                      p, ziperrlist[ziperror]);
  300.       }
  301.    }
  302. }
  303.  
  304. extern long thisread;
  305. extern int arcget __ARGS__(( void ));
  306.  
  307. void catalog()
  308. {
  309.    register long thislen;
  310.    register reverse = FALSE, skipped = FALSE;
  311.    register char *p;
  312.    static no_mem = FALSE;
  313.    short nx = 1, allx; long xinfo;
  314.    extern char ofname[];
  315.    register c;
  316.  
  317.    p = hblock->m.name;
  318.    c = hblock->m.filetype;
  319.  
  320.    if (v_flag) prmode(prefix(), (int)(st.st_mode));
  321.    if ((c == TF_OLD || c == TF_REG) && (nx=isextent(&allx, &xinfo)) < 1) {
  322.       if (st.st_size <= codesize) {
  323.          reverse = TRUE;
  324.       } else if (pktype == PKfLZW) {
  325.          register i, j;
  326.  
  327.          i = strlen(hblock->m.name);
  328.          if (hblock->m.name[--i] == 'Z' && hblock->m.name[--i] == '.') {
  329.             p = strncpy(ofname, hblock->m.name, MAXTNAME);
  330.             (void)z_getmem(BITS);
  331.             codesize = 0; thisread = 0;
  332.             if ((j = dbegin(arcget)) == 0) {
  333.                do {
  334.                   if ((j = dpiece(pk_out, pksize)) > 0) codesize += j;
  335.                } while (j == pksize);
  336.                skipped = TRUE;
  337.             } else if (j > 0) {
  338.                bacouple(); /* file is not in compressed format */
  339.             } else if (!no_mem) {
  340.                (void)fprintf(myout, "Tar: not enough memory to uncompress\n");
  341.                no_mem = TRUE;
  342.             }
  343.          }
  344.       }
  345.       thislen = codesize > st.st_size ? codesize : st.st_size;
  346.    } else {
  347.       thislen = st.st_size;
  348.    }
  349.    if (v_flag) {
  350.       (void)fprintf(myout, " %3d/%1d ", st.st_uid, st.st_gid);
  351.       if (c == TF_CHR || c == TF_BLK) {
  352.          (void)fprintf(myout,
  353.             pkfile ? "%10d,%-5d " : "%3d,%-3d ", dmajor, dminor);
  354.       } else {
  355.          (void)fprintf(myout, "%7ld ", reverse ? thislen : st.st_size);
  356.          if (pkfile) {
  357.             if ((c == TF_OLD || c == TF_REG) && st.st_size <= codesize) {
  358.                (void)fprintf(myout,
  359.                   reverse && hblock->m.srcsum[1] != 'x' ?
  360.                      "{%7ld} " : "(%7ld) ",
  361.                   reverse ? st.st_size : codesize);
  362.             } else {
  363.                (void)fprintf(myout, "          ");
  364.             }
  365.          }
  366.       }
  367.    }
  368.    (void)fprintf(myout, "%-.*s", MAXTNAME, p);
  369.  
  370.    switch (c) {
  371.       case TF_LNK:
  372.       case TF_SYM:
  373.          if (v_flag) (void)fprintf(myout, "\n");
  374.          (void)fprintf(myout, " %s to %s\n",
  375.             c == TF_SYM ? "symlink" : "linked",
  376.             hblock->m.linkname);
  377.          break;
  378.       case TF_OLD:
  379.       case TF_REG:
  380.          if (nx >= 1) {
  381.             if (v_flag) (void)fprintf(myout, "\n");
  382.             (void)fprintf(myout, " [extent #%d of %d]", nx, allx);
  383.             if (v_flag) (void)fprintf(myout, " %ld bytes total", xinfo);
  384.          }
  385.       case TF_CHR: case TF_BLK:
  386.       case TF_DIR: case TF_QUE: case TF_CTG:
  387.       case GF_DMP: case GF_VOL:
  388.          (void)fprintf(myout, "\n");
  389.          break;
  390.       case GF_MUL:
  391.          if (v_flag) (void)fprintf(myout, "\n");
  392.          (void)soctul(hblock->x.offset, &xinfo);
  393.          (void)fprintf(myout, "[from %ld to %ld]",
  394.                               xinfo, xinfo+st.st_size-1);
  395.          (void)fprintf(myout, "\n");
  396.          break;
  397.       default:
  398.          if (v_flag) (void)fprintf(myout, "\n");
  399.          (void)fprintf(myout, _unknown, c);
  400.    }
  401.    if (nx < 1 && v_flag && j_flag && /*dummy*/!skipped &&
  402.        hblock->m.comment[0] && !ismagic()) {
  403.       (void)fprintf(myout, "> %s\n", hblock->m.comment);
  404.    }
  405.    if (usize()) {
  406.       if (!skipped) skipfile();
  407.       allbytes += thislen;
  408.    }
  409.    ++allfiles;
  410. }
  411.  
  412. static char *cutname __ARGS__((register char *p));
  413.  
  414. static char *cutname(p)
  415. register char *p;
  416. {
  417.    register j;
  418.  
  419.    if (nonest) {
  420.       j = strlen(p);
  421.       while (j>0 && p[j-1] != '/'
  422. #ifdef MSDOS
  423.              && p[j-1] != ':'
  424. #endif
  425.             ) --j;
  426.       p += j;
  427.    } else {
  428. #ifdef MSDOS
  429.       if (deldrv && p[1] == ':' &&
  430.                    (p[0]>='A' && p[0]<='Z' || p[0]>='a' && p[0]<='z'))
  431.          p += 2;
  432. #endif
  433.       if (dslash && *p == '/') ++p;
  434.    }
  435.    return p;
  436. }
  437.  
  438. void extract()
  439. {
  440.    register j, k;
  441.    register char *p;
  442.    extern int makedir __ARGS__((char *, int));
  443.    extern int testdir __ARGS__((char *));
  444.  
  445.    p = cutname(hblock->m.name);
  446.    if (u_flag) {
  447.       long mtm;
  448.       if ((mtm=mtime(p)) != -1L && mtm >= st.st_mtime) {
  449.          if (usize()) skipfile(); return;
  450.       }
  451.    }
  452.    if (w_flag && !okwork('x', prefix(), &st, p)) {
  453.       if (usize()) skipfile(); return;
  454.    }
  455.    if ((j=strlen(p)-1) >= 0 && p[j] == '/') {/* directory with permissions */
  456.       if (testdir(p) != TRUE) return;
  457.       p[j] = '\0';
  458.    } else if (hblock->m.filetype == TF_DIR || hblock->m.filetype == GF_DMP) {
  459.       k = FALSE;
  460.       if (makedir(p, FALSE) != 0) {
  461.          if (testdir(p) != TRUE || makedir(p, TRUE) != 0) k = TRUE;
  462.       }
  463.       if (usize()) skipfile();
  464.       if (k) return;
  465.    } else if (hblock->m.filetype == TF_LNK) {
  466.       makelink(p, cutname(hblock->m.linkname)); return;
  467.    } else if (hblock->m.filetype == TF_OLD || hblock->m.filetype == TF_REG ||
  468.               hblock->m.filetype == GF_MUL) {
  469.       if (restore(p) != 0) return;
  470. #ifdef UNIX
  471.    } else if (hblock->m.filetype == TF_CHR || hblock->m.filetype == TF_BLK ||
  472.               hblock->m.filetype == TF_QUE) {
  473.       st.st_mode &= 07777;
  474.       if (hblock->m.filetype != TF_QUE) {
  475.          st.st_mode |= hblock->m.filetype == TF_BLK ? S_IFBLK : S_IFCHR;
  476.          st.st_rdev  = makedev(dmajor, dminor);
  477.       } else {
  478.          st.st_mode |= S_IFIFO;
  479.          st.st_rdev  = 0;
  480.       }
  481.       j = 0;
  482.       k = FALSE;
  483.       do {
  484.          if (mknod(p, st.st_mode, st.st_rdev) == 0) break;
  485.       } while (++j < 2 && (k = testdir(p)) == TRUE);
  486.       if (j > 1) (void)fprintf(myout, "Tar: can\'t create \'%s\'\n", p);
  487.       if (j > 1 || k == ERROR) return;
  488.       if (v_flag) (void)fprintf(myout, "x %s\n", p);
  489. #endif
  490.    } else {
  491.       (void)fprintf(myout, unknown, p, hblock->m.filetype);
  492.       return;
  493.    }
  494. #ifdef UNIX
  495.    if (!o_flag) (void)chown(p, (int)st.st_uid, (int)st.st_gid);
  496.    if (!m_flag) {
  497.       long t[2];
  498.  
  499.       t[0] = time(t);
  500.       t[1] = st.st_mtime;
  501.       (void)utime(p, t);
  502.    }
  503. #endif
  504. }
  505.  
  506. void uplist()
  507. {
  508.    register node *this; node *prev;
  509.  
  510.    if ((this = finditem(hblock->m.name, &prev, timehead)) == NONE) {
  511.       if ((this = additem(hblock->m.name, prev, &timehead)) == NONE) {
  512.          outmem(myout);
  513.       }
  514.       this->info.time = st.st_mtime;
  515.    } else {
  516.       if (this->info.time < st.st_mtime) this->info.time = st.st_mtime;
  517.    }
  518. }
  519.  
  520. void acctime()
  521. {
  522.    if (u_flag) uplist();
  523.    if (usize()) skipfile();
  524. }
  525.